package com.boyou.sytzc.ui

import android.annotation.SuppressLint
import android.app.ProgressDialog
import android.content.Intent
import android.os.*
import android.text.TextUtils
import android.view.*
import android.widget.*
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import com.baidu.location.BDLocation
import com.boyou.sytzc.R
import com.boyou.sytzc.core.appctx.AppData
import com.boyou.sytzc.data.database.CarNoOrRouteNoDB
import com.boyou.sytzc.data.database.table.GeoLocationDB
import com.boyou.sytzc.data.entity.RecordInfoEntity
import com.boyou.sytzc.data.event.DataChangedEvent
import com.boyou.sytzc.databinding.ActivityTakePhotoBinding
import com.boyou.sytzc.core.appctx.AppApplication
import com.boyou.sytzc.core.service.LocationService
import com.boyou.sytzc.utils.app.AppConfig
import com.boyou.sytzc.utils.app.configSystemBarStyleWithResources
import com.boyou.sytzc.utils.camera.CameraUtil
import com.boyou.sytzc.utils.database.RecordDbHelper
import com.boyou.sytzc.utils.io.ImageUtil
import com.google.gson.GsonBuilder
import com.hi.dhl.binding.viewbind
import com.squareup.picasso.Picasso
import com.yuge.yugecse.ext.uibasic.BasicActivity
import com.yuge.yugecse.util.device.ToastUtil
import com.yuge.yugecse.util.generic.ActivityUtil
import com.yuge.yugecse.util.io.FileUtil
import com.yuge.yugecse.util.time.TimeUtil
import org.simple.eventbus.Subscriber
import java.io.File
import java.lang.ref.WeakReference
import java.util.*

/**
 * 拍照页面
 */
@Suppress("DEPRECATION")
class TakePhotoActivity : BasicActivity(), CameraUtil.OnCameraListener {

    companion object {

        /** 请求码 **/
        const val REQ_CODE_VIEW_RECORD = 0x001

        /** 开始拍照 **/
        const val MSG_START_TAKEPHOTO = 0x002

        /** 保存文件OK **/
        const val MSG_SAVE_FILE_OK = 0x004

        /** 保存文件失败 **/
        const val MSG_SAVE_FILE_FAILED = 0x005
    }

    private val binding by viewbind<ActivityTakePhotoBinding>()
    private val appConfig by lazy { AppConfig.singleton() }//配置辅助类
    private val recordDbHelper by lazy { RecordDbHelper.getInstance(me) }//数据辅助对象
    private val carNoOrRouteNoDb by lazy { CarNoOrRouteNoDB.singleton() }
    private val messageHandler by lazy { MessageHandler(this) }//消息处理Handler
    private var cameraUtil: CameraUtil? = null//相机对象
    private var proDialog: ProgressDialog? = null//加载进度条
    private var autoTakePhotoTimer: Timer? = null//定时器对象
    private var modeType = 0//拍照模式
    private var modeName: String? = ""//模式名
    private var isWifiUpload = false//是否是wifi上传
    private var totalTakePhotoCount = 0//今日总的拍照次数（成功的）
    private var takePhotoTime: Long = 0//获取拍照的间隔时间
    private var isAutoTakePhoto = false//是否正在自动拍照
    private var limitCountDownTimer: LimitTakePhotoCountDownTimer? = null//拍照计时器

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        requestWindowFeature(Window.FEATURE_NO_TITLE)//去掉状态栏
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
            window.setFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN
            )
        super.onCreate(savedInstanceState)
        configSystemBarStyleWithResources(
            android.R.color.transparent,
            navigationBarColorId = android.R.color.transparent
        )
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val controller = window.insetsController
            controller?.hide(WindowInsets.Type.systemBars())
        }
        proDialog = ProgressDialog(me)//加载进度条
        cameraUtil = CameraUtil(me, binding.flRootContainer)//初始化相机对象
        cameraUtil?.initCamera(binding.svPhotoView)//初始化相机
        cameraUtil?.setOnCameraListener(this)//设置相机监听事件
        with(binding) {
            when (appConfig.isWifiUpload) {
                true -> tbWifiUploadSwitch.setToggleOn()
                else -> tbWifiUploadSwitch.setToggleOff()
            }
            tbWifiUploadSwitch.setOnToggleChanged { on ->
                isWifiUpload = on
                appConfig.isWifiUpload = isWifiUpload
            }
            sbSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
                override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
                    cameraUtil?.setCameraZoom(progress)
                }

                override fun onStartTrackingTouch(seekBar: SeekBar) {}

                override fun onStopTrackingTouch(seekBar: SeekBar) {}
            })
            //设置某些控件的初始值
            val data: Bundle? = intent?.extras
            if (data != null) {
                modeType = data.getInt("type", 0)
                modeName = data.getString("description")
            }
            imgCameraState.setImageResource(
                when (modeType) {
                    0 -> R.mipmap.ic_takephoto
                    else -> R.mipmap.ic_open_camera
                }
            ) //拍照按钮图片样式
            txtSelectMode.text = "模式：${modeName ?: ""}"
            //tvLocation.text = LocationService.locationInfo?.addrStr ?: "位置：获取中..."
        }
        setGlobalCarRouteNos()//生成全局的汽车号和路线号
        cameraUtil?.stopPreview()//停止相机预览
    }

    /** 控件点击事件 **/
    fun onViewClick(view: View) {
        when (view.id) {
            R.id.imgRefresh -> when (cameraUtil?.isSupportAutoFocus) {
                true -> when (cameraUtil?.isPreview) {
                    true -> cameraUtil?.autoFocus()
                    else -> ToastUtil.showGenericToast(me, "相机未开启，不能自动对焦")
                }
                else -> ToastUtil.showGenericToast(me, "相机硬件不支持自动对焦")
            }
            R.id.imgCameraState -> when (modeType) { //相机状态
                0 -> takePhotoWhenTypeIsCarMode() //装车模式拍照
                else -> takePhotoWhenTypeIsTimeMode() //计时模式拍照
            }
            R.id.imgBackHome -> {
                overridePendingTransition(
                    androidx.appcompat.R.anim.abc_fade_in,
                    androidx.appcompat.R.anim.abc_fade_out
                )
                finish() //返回上一个页面
            }
            R.id.imgViewDetail -> go2RecordListActivity(modeType) //查看
        }
    }

    /** 接收定位信息 **/
    @Subscriber
    fun onReceivedLocationChanged(location: BDLocation) {
        binding.tvLocation.text = "坐标：" + location.getLongitude().toString() + " , " + location.getLatitude().toString();
    }

    /**
     * 装车模式的拍照
     */
    private fun takePhotoWhenTypeIsCarMode() {
        val nowTime = System.currentTimeMillis()
        if (takePhotoTime != 0L && nowTime - takePhotoTime < appConfig.handleTimeSpan * 1000L) {
            // ToastUtil.showGenericToast(me,"拍照后" + (SysData.HANDLE_TAKE_PHOTO_TIME_SPAN / 1000) + "秒内不可再次拍照!");
            return
        }
        takePhotoTime = nowTime//记录拍照时间
        startTakePhoto(true)//开始拍照
    }

    /**
     * 计时模式的拍照
     */
    private fun takePhotoWhenTypeIsTimeMode() {
        if (!isAutoTakePhoto) {
            isAutoTakePhoto = true
            //计时模式的自动拍照
            if (autoTakePhotoTimer == null)
                autoTakePhotoTimer = Timer()
            autoTakePhotoTimer?.schedule(
                AutoTakePhotoTimerTask(), 0,
                appConfig.autoTimeSpan * 1000L
            )
        } else {
            isAutoTakePhoto = false
            cameraUtil?.stopPreview()//停止预览
            binding.imgCover.visibility = View.VISIBLE
            binding.imgCameraState.setImageResource(R.mipmap.ic_open_camera)
            //取消定时器任务
            if (autoTakePhotoTimer != null) {
                autoTakePhotoTimer?.cancel()
                autoTakePhotoTimer = null
            }
            if (limitCountDownTimer != null) {
                limitCountDownTimer?.onFinish()
                limitCountDownTimer?.cancel()
                limitCountDownTimer = null
            }
        }
    }

    /** 自动拍照的任务 **/
    internal inner class AutoTakePhotoTimerTask : TimerTask() {
        override fun run() {
            startTakePhoto(false)//开始照相
        }
    }

    /** 开始照相 **/
    private fun startTakePhoto(isWaitTime: Boolean): Unit =
        messageHandler.obtainMessage(MSG_START_TAKEPHOTO, isWaitTime).sendToTarget()

    /** 执行拍照 **/
    private fun doTakePhoto(isWaitTime: Boolean) {
        cameraUtil?.resumePreview()//开启预览
        binding.imgCover.visibility = View.GONE
        binding.imgCameraState.setImageResource(if (modeType == 0) R.mipmap.ic_takephoto else R.mipmap.ic_close_camera)
        ToastUtil.showGenericToast(me, "正在拍照...")
        Thread {
            if (isWaitTime) try {
                Thread.sleep((2 * 1000).toLong())
            } catch (e: Exception) {
                e.printStackTrace()
            }
            cameraUtil?.takePhoto { data, _ ->
                try {
                    //保存照片数据,初始化进度框
                    if (proDialog == null)
                        proDialog = ProgressDialog(me)
                    proDialog?.setMessage("正在保存图片...")
                    proDialog?.show()
                    val currentDate = Date() //获取当前日期
                    val filename = AppData.IMAGE_CACHE_PATH +
                            TimeUtil.format(currentDate, "yyyyMMdd") +
                            "/${TimeUtil.format(currentDate, "yyyyMMddHHmmss")}.jpg"
                    val saveData = ImageUtil.finalCompress(data, 720, 1280)
                    FileUtil.write2file(filename, saveData)//存储图片到本地
                    messageHandler.obtainMessage(MSG_SAVE_FILE_OK, filename).sendToTarget()
                } catch (e: Exception) {
                    e.printStackTrace()
                    messageHandler.obtainMessage(MSG_SAVE_FILE_FAILED).sendToTarget()
                }
            }
        }.start()
    }

    /** 查看记录列表 **/
    private fun go2RecordListActivity(type: Int) {
        if (modeType == 1) {
            //取消定时器任务
            if (autoTakePhotoTimer != null) {
                autoTakePhotoTimer?.cancel()
                autoTakePhotoTimer = null
            }
        }
        with(Bundle()) {
            putInt("type", type)
            ActivityUtil.goForward(me, RecordListActivity::class.java, REQ_CODE_VIEW_RECORD, this)
        }
    }

    /**
     * 储存记录到本地
     *
     * @param filename   图片名称
     * @param bdLocation 地理信息
     * @return true - 保存成功，  false - 保存失败
     */
    @SuppressLint("SetTextI18n")
    private fun saveRecord2Local(filename: String, bdLocation: BDLocation?): Boolean =
        with(RecordInfoEntity()) {
            try {
                deviceNo = AppApplication.deviceNoManager.deviceNo
                sjNo = appConfig.driverNoData
                time = Date().time
                type = modeType + 1//1.装车模式  2.计时模式
                posi = if (binding.cbLoadPlace.isChecked) 1 else 2//1.装土点 2.卸土点
                carNo = binding.aspCarNo.selectedItem?.toString() ?: ""//汽车编号
                lineNo = binding.aspLineNo.selectedItem?.toString() ?: ""//路线编号
                picture = filename
                isUpload = 0//默认为未上传，1为已上传
                if (bdLocation != null && !TextUtils.isEmpty(bdLocation.addrStr)) {
                    locx = bdLocation.longitude
                    locy = bdLocation.latitude
                    address = bdLocation.addrStr
                } else {
                    locx = 0.0
                    locy = 0.0
                    address = "无GPS信号,无地址信息"
                }

                val geoLocs = GeoLocationDB.getInstance(this@TakePhotoActivity).findUnUpload()
                packet = GsonBuilder().excludeFieldsWithoutExposeAnnotation()
                    .setDateFormat("yyyy-MM-dd HH:mm:ss").create().toJson(geoLocs)
                recordDbHelper?.addRecord(this)//保存至本地

                if (geoLocs != null && geoLocs.size > 0)
                    for (i in geoLocs.indices)
                        geoLocs[i].isUpload = true
                GeoLocationDB.getInstance(this@TakePhotoActivity).put(geoLocs)

                binding.txtRecordCount.text = "今日登记次数：${++totalTakePhotoCount}"
                Picasso.get().load(File(filename)).into(binding.imgCover)
                binding.imgCover.visibility = View.VISIBLE
                ToastUtil.showGenericToast(me, "数据记录成功!")
                return true
            } catch (e: Exception) {
                e.printStackTrace()
                ToastUtil.showGenericToast(me, "数据记录异常，请重新拍照!")
                resumePreview()//恢复相机预览
            }
            return false
        }

    override fun onPreviewStateChanged(isPreview: Boolean) {
        binding.sbSeekBar.isEnabled = isPreview//设置是否可用
    }

    override fun onSupportZoom(isSupport: Boolean, value: Int, max: Int) {
        binding.sbSeekBar.progress = value
        binding.sbSeekBar.max = max
        binding.sbSeekBar.visibility = if (isSupport) View.VISIBLE else View.GONE
    }

    @SuppressLint("SetTextI18n")
    override fun onResume() {
        super.onResume()
        cameraUtil?.stopPreview()//停止预览
        try {
            val info = recordDbHelper?.getTodayUploadInfo(modeType + 1)
            totalTakePhotoCount = info?.total ?: 0
            binding.txtRecordCount.text = "今日登记次数：${info?.total ?: 0}"
            binding.txtUploadOkCount.text = "上传成功 ${info?.hadUpload ?: 0} 张"
            binding.txtUploadFailedCount.text = "失败 ${info?.waitUpload ?: 0} 张"
            val picture = recordDbHelper?.getLastRecordImage(modeType + 1)
            if (!picture.isNullOrEmpty())
                Picasso.get().load(File(picture)).into(binding.imgCover)//覆盖层
        } catch (e: Exception) {
            e.printStackTrace()
            binding.imgCover.visibility = View.VISIBLE
        }

    }

    override fun onSaveInstanceState(outState: Bundle) {
        outState.putInt("type", modeType)
        outState.putString("description", modeName)
        super.onSaveInstanceState(outState)
    }

    override fun onRestoreInstanceState(savedInstanceState: Bundle) {
        super.onRestoreInstanceState(savedInstanceState)
        modeType = savedInstanceState.getInt("type", 0)
        modeName = savedInstanceState.getString("description")
    }


    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == REQ_CODE_VIEW_RECORD) {
            if (isAutoTakePhoto) { //计时模式的自动拍照
                if (autoTakePhotoTimer == null) autoTakePhotoTimer = Timer()
                autoTakePhotoTimer?.schedule(
                    AutoTakePhotoTimerTask(),
                    appConfig.autoTimeSpan * 1000L,
                    appConfig.autoTimeSpan * 1000L
                )
            }
        }
    }

    override fun onStop() {
        cameraUtil?.releaseCamera()
        super.onStop()
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        if (event.action == KeyEvent.ACTION_DOWN) {
            when (keyCode) {
                KeyEvent.KEYCODE_BACK, KeyEvent.KEYCODE_MOVE_HOME -> {
//                    cameraUtil?.stopPreview()//关闭预览
//                    if (autoTakePhotoTimer != null) {
//                        autoTakePhotoTimer?.cancel()
//                        autoTakePhotoTimer = null
//                    }
//                    ActivityUtil.goBack(me)
                    return true
                }
                KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_VOLUME_UP -> {
                    binding.imgCameraState.performClick()
                    return true
                }
                else -> {
                }
            }
        }
        return super.onKeyDown(keyCode, event)
    }

    /**
     * 恢复相机预览
     */
    private fun resumePreview() {
        ToastUtil.showGenericToast(me, "数据记录异常，请重新拍照!")
        binding.imgCover.visibility = View.GONE
        binding.imgCover.setImageResource(0)
        binding.imgCameraState.setImageResource(if (modeType == 0) R.mipmap.ic_takephoto else R.mipmap.ic_close_camera)
        cameraUtil?.resumePreview()//唤起预览操作
    }

    /**
     * 生成Button组
     */
    private fun setGlobalCarRouteNos() {
        val carNos = carNoOrRouteNoDb.findByType(0).map { it.name }
        val lineNos = carNoOrRouteNoDb.findByType(1).map { it.name }
        binding.aspCarNo.adapter = ArrayAdapter(
            this, R.layout.item_for_spinner_drop_list, android.R.id.text1, carNos
        )
        binding.aspLineNo.adapter = ArrayAdapter(
            this, R.layout.item_for_spinner_drop_list, android.R.id.text1, lineNos
        )
        binding.aspCarNo.setSelection(0, true)
        binding.aspLineNo.setSelection(0, true)
    }

    @SuppressLint("SetTextI18n")
    @Subscriber
    fun onDataChangedEvent(event: DataChangedEvent): Unit = try {
        val info = recordDbHelper?.getTodayUploadInfo(modeType + 1)
        totalTakePhotoCount = (info?.total ?: 0)
        binding.txtRecordCount.text = "今日登记次数：${info?.total ?: 0}"
        binding.txtUploadOkCount.text = "上传成功 ${info?.hadUpload ?: 0} 张"
        binding.txtUploadFailedCount.text = "失败 ${info?.waitUpload ?: 0} 张"
    } catch (e: Exception) {
        e.printStackTrace()
    }

    class MessageHandler(activity: TakePhotoActivity) : Handler() {

        private val activityReference: WeakReference<TakePhotoActivity> = WeakReference(activity)

        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            val activity = activityReference.get()
            if (activity != null) {
                when (msg.what) {
                    MSG_START_TAKEPHOTO//开始拍照
                    -> activity.doTakePhoto(java.lang.Boolean.valueOf(msg.obj.toString()))
                    MSG_SAVE_FILE_OK//储存文件成功
                    -> {
                        if (activity.proDialog != null && activity.proDialog?.isShowing == true)
                            activity.proDialog?.dismiss()//关闭当前进度条
                        activity.cameraUtil?.stopPreview()//停止预览
                        val file = File(msg.obj.toString())
                        if (!TextUtils.isEmpty(msg.obj.toString()) && file.exists()) {
                            Picasso.get().load(file).into(activity.binding.imgCover)//覆盖层
                            val isSaveOk = activity.saveRecord2Local(
                                file.absolutePath,
                                LocationService.locationInfo
                            )//储存记录到本地
                            //如果保存成功并且处于挖机模式，自动切换车辆装载类型
                            if (activity.modeType == 0 && isSaveOk) {
                                val isLoadType1 = activity.binding.cbLoadPlace.isChecked
                                activity.binding.rgPlace.check(if (isLoadType1) R.id.cbUnloadPlace else R.id.cbLoadPlace)
                            }
                        }
                        //拍照时间计时器
                        if (activity.limitCountDownTimer == null) {
                            val totalTimeMillions = activity.appConfig.handleTimeSpan * 1000L
                            activity.limitCountDownTimer =
                                LimitTakePhotoCountDownTimer(totalTimeMillions, 1000, activity)
                        }
                        activity.limitCountDownTimer?.start()
                    }
                    MSG_SAVE_FILE_FAILED//存储文件失败
                    -> {
                        if (activity.proDialog != null && activity.proDialog?.isShowing == true)
                            activity.proDialog?.dismiss()//关闭当前进度条
                        activity.cameraUtil?.stopPreview()//停止预览
                        ToastUtil.showGenericToast(activity.me, "照片保存失败，请重新拍照！")
                        activity.resumePreview()//恢复相机预览
                    }
                }
            }
        }
    }

    /**
     * 限制时间拍照计时器
     */
    class LimitTakePhotoCountDownTimer(
        millisInFuture: Long,
        countDownInterval: Long,
        activity: TakePhotoActivity
    ) : CountDownTimer(millisInFuture, countDownInterval) {

        private val activityReference: WeakReference<TakePhotoActivity> = WeakReference(activity)

        override fun onTick(millisUntilFinished: Long) {
            val activity = activityReference.get()
            if (activity == null)
                this.cancel()
            else {
                if (activity.binding.txtDownCounter.visibility == View.GONE)
                    activity.binding.txtDownCounter.visibility = View.VISIBLE
                activity.binding.txtDownCounter.text = (millisUntilFinished / 1000).toString()
            }
        }

        override fun onFinish() {
            val activity = activityReference.get()
            if (activity != null) { //隐藏时间限制
                activity.binding.txtDownCounter.text = "0"
                activity.binding.txtDownCounter.visibility = View.GONE
            }
        }

    }

}
